import axios from 'axios'
// import store from '@/store'
// import types from '@/store/types'
// 既默认导入，又按需导入，中间用逗号分隔
import store, { mutations as rootMutations } from '../store/index'
import { refreshToken } from '@/api/user'
import router from '@/router'
import { Dialog, Toast } from 'vant'

const request = axios.create({
  // baseURL: 'http://geek.itheima.net'
  baseURL: 'http://toutiao.itheima.net/'
})

// 添加一个请求拦截器
// 在 所有 请求发出去之前，都会先进入这个拦截器执行，并把当前的请求配置作为参数 (reqConfig) 传进来
// 将拦截器执行的返回值作为最终的请求配置，再去发送请求
// 千万千万不要忘了写 return，如果不写 return，那么就相当于把请求配置改成了 undefined
request.interceptors.request.use((reqConfig) => {
  // 我们就可以在这里 对请求配置 做点手脚
  // 当有 token 的时候，我们就加到请求头里面
  // if (store.state.userToken && store.state.userToken.token) {
  if (store.state.userToken?.token) {
    // 这个是不是直接给 headers 赋值为一个新对象了
    // reqConfig.headers = {
    //   Authorization: `Bearer ${store.state.userToken?.token}`
    // }
    if (reqConfig.isRefreshToken) {
      reqConfig.headers.Authorization = `Bearer ${store.state.userToken?.refresh_token}`
    } else {
      reqConfig.headers.Authorization = `Bearer ${store.state.userToken?.token}`
    }
    // 下面的代码和上面是等价的
    // reqConfig.headers.Authorization = `Bearer ${
    //   reqConfig.isRefreshToken
    //   ? store.state.userToken?.refresh_token
    //   : store.state.userToken?.token
    // }`
  }
  return reqConfig
})

// 所有请求，响应成功后，都会先进入这个响应拦截器处理完，再进到实际发请求的位置的后续操作
// 添加一个相应拦截器，判断请求是否是因为 token 失效导致的失败
// axios 基于 Promise，又因，Promise 实例的 .then 是有默认值
request.interceptors.response.use(undefined, err => {
  if (err.response.status === 401) { // 说明是因为 token 失效导致的
    // 通过观察发现，err.config 就是上一次发送请求时的配置对象，那么，在刷新 token 后，我们只要拿着这份配置，重新发一次请求就行了
    // 先去刷新 token
    return Promise.resolve().then(() => {
      if (store.state.userToken) {
        return refreshToken()
      } else {
        throw new Error('token 已被清除')
      }
    }).then((res) => {
      // 刷新成功，更新 vuex 和 本地存储中的 token
      store.commit(rootMutations.changeUserToken.nsname, { ...store.state.userToken, token: res.data.data.token })
      // 下面这个注释的代码和上面的是等价的
      // store.commit(rootMutations.changeUserToken.nsname, {
      //   refresh_token: store.state.userToken.refresh_token,
      //   token: res.data.data.token
      // })
      // 此时，token 就是有效的了，那么，就可以去发上一次失败的请求了
      return request(err.config)
    }, () => {
      // Toast.fail({ message: '你只怕有个把星期没来了，先去登录吧~' })

      // 要清空 userToken 数据
      store.commit(rootMutations.changeUserToken.nsname, null)

      // 刷新失败，去登录吧
      return Dialog.confirm({
        title: '你确定要去登录吗？',
        message: '登录已过期，需要重新登录才能继续操作！'
      }).then(() => {
        // 其实走到这，去登录后，就不用干啥了，要中断本次链式调用（链式中断）
        // returnUrl：获取到当前地址，传到登录页去，在登录页就可以获取到这个查询参数，
        // 如果有，则登录成功后跳回来，如果没有，就跳我的页面
        router.push({ name: 'login', query: { returnUrl: window.location.hash.slice(1) } })
        // return new Promise(() => {}) // 返回一个永远是 pending 的 Promise 实例
        return new Promise(() => {})
      })
    })
    // 重新发送上一次失败的请求
  } else {
    Toast.fail(err.response.data.message)
  }
  throw err
})

export default request
